﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Anagramme.Server.Model;
using Morphalou;

namespace MorphalouFileConverter
{
    class Program
    {
        const string morphalouFileName = "Morphalou-2.0.xml";
        const string convertedFileName = "dictionary.xml";

        const int minWordLength = 5;
        const int maxWordLength = 8;
        const int minAnagramme = 5;

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "args")]
        static void Main(string[] args)
        {
            string morphalouFilePath = Path.Combine(Environment.CurrentDirectory, morphalouFileName);
            Lexicon lexicon = null;

            using(StreamReader rd = new StreamReader(morphalouFilePath))
            {
                MorphalouSerializer sr = new MorphalouSerializer();
                lexicon = (Lexicon)sr.Deserialize(rd);
            }

            List<LexicalEntry> entries = lexicon.Items.OfType<LexicalEntry>().ToList();
            Dictionary<string, List<string>> words = new Dictionary<string, List<string>>();

            foreach (LexicalEntry entry in entries)
            {
                foreach (FormSet formSet in entry.FormSet)
                {
                    List<LemmatizedForm> lemmatizedForms = formSet.LemmatizedForm.ToList();
                    foreach (LemmatizedForm lemmatizedForm in lemmatizedForms)
                    {
                        string orthography = lemmatizedForm.Orthography.First().Value.ToUpperInvariant();
                        string normalizedOrthography = CleanOrthography(orthography);
                        string pattern = ComputePattern(orthography);
                        if (orthography.Length >= minWordLength 
                            && orthography.Length <= maxWordLength 
                            && orthography.Length == pattern.Length)
                        {
                            if (!words.ContainsKey(pattern))
                            {
                                words.Add(pattern, new List<string>());
                            }
                            if (!words[pattern].Contains(normalizedOrthography))
                            {
                                words[pattern].Add(normalizedOrthography);
                            }
                        }
                    }
                }
            }

            Dictionary<string, List<string>> wordsToAdd = new Dictionary<string, List<string>>();
            
            foreach (KeyValuePair<string, List<string>> item in words)
            {
                if (item.Value.Count >= minAnagramme)
                {
                    wordsToAdd.Add(item.Key, item.Value);
                }
            }

            Dictionary dictionary = new Dictionary();
            foreach (KeyValuePair<string, List<string>> item in wordsToAdd)
            {
                foreach (string word in item.Value)
                {
                    dictionary.Words.Add(new Word() { Orthography = word, Pattern = item.Key, Length = word.Length });
                }
            }

            string convertedFilePath = Path.Combine(Environment.CurrentDirectory, convertedFileName);

            using (StreamWriter wr = new StreamWriter(convertedFilePath))
            {
                DictionarySerializer sr = new DictionarySerializer();
                sr.Serialize(wr, dictionary);
            }
        }

        static string ComputePattern(string orthography)
        {
            string normalizedOrthography = CleanOrthography(orthography);
            string pattern = new string(normalizedOrthography
                .ToCharArray()
                .OrderBy(c => c).ToArray());
            return pattern;
        }

        static string CleanOrthography(string orthography)
        {
            string normalizedOrthography = new string(orthography
                .ToUpperInvariant()
                .Normalize(System.Text.NormalizationForm.FormD)
                .ToCharArray()
                .Where(c => CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.UppercaseLetter)
                .ToArray());
            return normalizedOrthography;
        }
    }
}
